//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.ScientificWorkflow.ManagementStudioControls.RegistryManagerModule
{
    using System;
    using System.Collections.ObjectModel;
    using System.Windows;
    using System.Windows.Input;
    using ManagementStudioServices.Interfaces;
    using Microsoft.Practices.Unity;
    using SR = Microsoft.Research.DataLayer;
    using Microsoft.Research.ScientificWorkflow.ManagementStudioModels;
    using System.Linq;
    using Microsoft.Research.ScientificWorkflow.TridentUtilities;
    using System.Collections.Generic;
    using System.Globalization;

    /// <summary>
    /// Interaction logic for CategoryPicker.xaml
    /// </summary>
    public partial class CategoryPicker : Window
    {
        /// <summary>
        /// The category items.
        /// </summary>
        private ObservableCollection<CategoryViewModel> categoryItems = new ObservableCollection<CategoryViewModel>();
       
        /// <summary>
        /// Occurs when category picker closes.
        /// </summary>
        public event EventHandler CategoryPickerClose;
        
        /// <summary>
        /// Occurs on category picker ok.
        /// </summary>
        public event EventHandler<CategoryEventArgs> CategoryPickerOk;

        /// <summary>
        /// Initializes a new instance of the <see cref="CategoryPicker"/> class.
        /// </summary>
        /// <param name="container">The container.</param>
        /// <param name="categoryType">Type of the category.</param>
        public CategoryPicker(IUnityContainer container, CategoryType categoryType, CategoryViewModel modelToSelect)
        {
            try
            {
                InitializeComponent();
                IRegistryManagerService registryManagerService = container.Resolve<IRegistryManagerService>();
                SR.Namespace root = null;
                if (categoryType == CategoryType.Activity)
                {
                    root = registryManagerService.GetActivityCategories();
                    this.txtHeader.Text = string.Format(CultureInfo.CurrentCulture, ManagementStudioResourceManager.GetString("ActivityCategoryPickerHeader"));
                }
                else if (categoryType == CategoryType.Workflow)
                {
                    root = registryManagerService.GetWorkflowCategories();
                    this.txtHeader.Text = string.Format(CultureInfo.CurrentCulture, ManagementStudioResourceManager.GetString("WorkflowCategoryPickerHeader"));
                }

                CategoryViewModel rootModel = new CategoryViewModel(root, null, categoryType, null, true);
                this.categoryItems.Add(rootModel);

                // If the category is workflow, add My Workflow nodes.
                if (categoryType == CategoryType.Workflow)
                {
                    List<SR.Namespace> namespaces = CategoryPicker.ReadWorkflowCategories(TridentAuthentication.LoggedInUser);

                    // Create category models for each namespace present.
                    foreach (SR.Namespace cat in namespaces)
                    {
                        CategoryViewModel catModel = new CategoryViewModel(cat, rootModel, categoryType, null, true);
                        this.categoryItems.Add(catModel);
                    }
                }

                if (modelToSelect != null)
                {
                    CategoryViewModel selectModel = modelToSelect.GetModelById(modelToSelect, this.categoryItems.Cast<BaseRegMgrModel>()) as CategoryViewModel;
                    if (selectModel != null)
                    {
                        selectModel.IsSelected = true;
                    }
                }

                this.treeVwCategoryPicker.ItemsSource = this.categoryItems;
            }
            catch (TridentCustomException exception)
            {
                TridentErrorHandler.HandleTridentCustomExceptionInUI(exception);
            }
            catch (Exception exception)
            {
                TridentErrorHandler.HandleKnownExceptionsInUI(exception);
            }
        }

        /// <summary>
        /// Get all the workflow categories from the registry.
        /// </summary>
        /// <param name="c">The registry connection.</param>
        /// <param name="user">The user for whom the workflows need to be retreived.</param>
        /// <returns>The namespace collection.</returns>
        private static List<SR.Namespace> ReadWorkflowCategories(SR.User user)
        {
            List<SR.Namespace> childrenCollection = new List<SR.Namespace>();
            SR.Namespace workflowRoot = user.WorkflowRoot;
            if (workflowRoot == null)
            {
                TridentErrorHandler.ThrowTridentCustomException(TridentErrorConstants.ErrorNumber4000031,
                    TridentResourceManager.GetString("WorkflowCategoryError"));
            }

            workflowRoot.Children.Refresh();
            foreach (SR.Namespace nameSpace in workflowRoot.Children)
            {
                if (user.Name.Equals("System", StringComparison.OrdinalIgnoreCase) ||
                    (nameSpace.User != null && ((SR.IObject)nameSpace.User).ID == ((SR.IObject)user).ID))
                {
                    nameSpace.Activitys.Refresh();
                    childrenCollection.Add(nameSpace);
                }
            }
            return childrenCollection;
        }

        /// <summary>
        /// Drags the on preview mouse left button down.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
        private void DragOnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.DragMove();
        }

        /// <summary>
        /// Called when category picker closes.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void OnCategoryPickerClose(object sender, RoutedEventArgs e)
        {
            if (this.CategoryPickerClose != null)
            {
                this.CategoryPickerClose.Invoke(sender, e);
            }
        }

        /// <summary>
        /// Called on category picker ok.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void OnCategoryPickerOk(object sender, RoutedEventArgs e)
        {
            if (this.CategoryPickerOk != null && this.treeVwCategoryPicker.SelectedItem != null)
            {
                this.CategoryPickerOk.Invoke(sender, new CategoryEventArgs(this.treeVwCategoryPicker.SelectedItem as CategoryViewModel));
            }
        }
    }

    /// <summary>
    /// Event args containing the CategoryViewModel.
    /// </summary>
    public class CategoryEventArgs : EventArgs
    {
        /// <summary>
        /// Gets or sets the category picker selected model.
        /// </summary>
        /// <value>The category picker selected model.</value>
        public CategoryViewModel CategoryPickerSelectedModel
        {
            get;
            set;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CategoryEventArgs"/> class.
        /// </summary>
        /// <param name="categoryPickerSelectedModel">The category picker selected model.</param>
        public CategoryEventArgs(CategoryViewModel categoryPickerSelectedModel)
        {
            this.CategoryPickerSelectedModel = categoryPickerSelectedModel;
        }
    }
}
